package org.bot.socket.impl;

import com.alibaba.fastjson.JSONObject;
import org.bot.client.util.Bean;
import org.bot.socket.auth.CertificateManage;
import org.bot.socket.config.SocketConfig;
import org.bot.socket.drive.Drive;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author 沧月
 * @create 0002 2023/10/2 15:12
 * @description <description class purpose>
 */

public class SocketClient extends WebSocketClient {

    static Logger logger = LoggerFactory.getLogger(SocketClient.class);

    public static SocketClient CLIENT;

    public static SocketConfig SOCKET_CONFIG;

    public static SocketClient build(SocketConfig config) throws URISyntaxException {
        if (SOCKET_CONFIG == null) {
            SOCKET_CONFIG = config;
        }

        Map<String, String> httpHeaders = new HashMap<>();
        httpHeaders.put("clientId", SOCKET_CONFIG.getClientId());
        httpHeaders.put("secretKey", SOCKET_CONFIG.getSecretKey());
        httpHeaders.put("mac", SOCKET_CONFIG.getMac());
        CLIENT = new SocketClient(new URI(SOCKET_CONFIG.getUrl()), httpHeaders);
        return CLIENT;
    }

    public SocketClient(URI serverUri, Map<String, String> head) {
        super(serverUri, head);
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        logger.info("正在与服务端建立连接.......");
    }

    @Override
    public void onMessage(String data) {
        JSONObject message = JSONObject.parseObject(data);
        switch (message.getString("type")) {
            case "flow":
                Drive.flowExecute.execute(message, SOCKET_CONFIG.getClientId());
                break;
            case "event":
                logger.info("开始上报客户端信息.......");
                Drive.pushServer.clientEvent(SOCKET_CONFIG.getClientId(), Bean.getEventList());
                logger.info("上报完成.......");
                break;
            case "connect":
                logger.info("连接成功.......");
                if (!SOCKET_CONFIG.isStatus()) {
                    //添加客户端连接证书
                    try {
                        CertificateManage.writeCertificate(SOCKET_CONFIG);
                    } catch (Exception e) {
                        logger.error("客户端发生错误,即将退出客户!");
                        try {
                            Thread.sleep(10000);
                        } catch (InterruptedException e1) {
                            logger.error("连接异常:", e1);
                        }
                        CLIENT.close();
                        System.exit(-1);
                    }
                }
                break;
            case "heartbeat":
                logger.info("收到来自服务端的心跳包..");
                CLIENT.send(new JSONObject().fluentPut("msgType", "heartbeat").toString());
                break;
            case "interrupt":
                logger.info("收到任务终止指令，开始终止正在执行任务..");
                Drive.flowExecute.interrupt();
                break;
        }
    }

    @Override
    public void onClose(int code, String message, boolean b) {
        logger.error("连接失败，[{}]错误消息为：{}", code, message);
        if (code > 4300 && code < 4400) {
            logger.warn("客户端将在10s后自动关闭");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e1) {
                logger.error("连接异常:", e1);
            }
            CLIENT.close();
            System.exit(-1);
        }
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    SocketClient.build(SOCKET_CONFIG).connect();
                } catch (Exception e) {
                    logger.error("服务端连接失败，正在尝试重新连接...", e);
                }
            }
        }, 60 * 1000);
    }

    @Override
    public void onError(Exception e) {
        logger.error(e.getMessage(), e);
    }
}
